package service

import (
	dao "go-bluebell/dao/mysql"
	"go-bluebell/dao/redis"
	"go-bluebell/model"
	"go-bluebell/utils"
	"strconv"

	"go.uber.org/zap"
)

func GetCommunityList() (communityList []*model.Community, err error) {
	return dao.GetCommunityList()
}

func GetCommunityDetail(communityID int64) (communityDetail *model.CommunityDetail, err error) {
	return dao.GetCommunityDetailByID(communityID)
}

func CreatePost(p *model.Post) (err error) {
	p.PostID = utils.GenID()
	err = dao.CreatePost(p)
	if err != nil {
		return err
	}
	err = redis.CreatePost(p.PostID, p.CommunityID)
	return
}

func GetPostByID(postID int64) (postDetail *model.ApiPostDetail, err error) {
	// 查询并组合我们想要的帖子数据

	// 根据帖子id查询帖子信息
	post, err := dao.GetPostByID(postID)
	if err != nil {
		return nil, err
	}

	// 根据作者id查询作者信息
	author, err := dao.GetAuthorByID(post.AuthorID)
	if err != nil {
		return nil, err
	}

	// 根据社区id查询社区信息
	community, err := dao.GetCommunityDetailByID(post.CommunityID)
	if err != nil {
		return nil, err
	}

	// 组合数据
	postDetail = &model.ApiPostDetail{
		AuthorName:      author.Username,
		Post:            post,
		CommunityDetail: community,
	}

	return
}

func GetPostList(page, size int) (postList []*model.Post, err error) {
	posts, err := dao.GetPostList(page, size)
	if err != nil {
		return nil, err
	}

	postList = make([]*model.Post, 0, len(posts))

	for _, post := range posts {
		// 根据作者id查询作者信息
		author, err := dao.GetAuthorByID(post.AuthorID)
		if err != nil {
			zap.L().Error("dao.GetAuthorByID(post.AuthorID) failed", zap.Int64("post.AuthorID", post.AuthorID), zap.Error(err))
			continue
		}

		// 根据社区id查询社区信息
		community, err := dao.GetCommunityDetailByID(post.CommunityID)
		if err != nil {
			zap.L().Error("dao.GetCommunityDetailByID(post.CommunityID) failed", zap.Int64("post.CommunityID", post.CommunityID), zap.Error(err))
			continue
		}

		postDetail := &model.ApiPostDetail{
			AuthorName:      author.Username,
			Post:            post,
			CommunityDetail: community,
		}

		postList = append(postList, postDetail.Post)
	}

	return
}

func GetPostList2(p *model.PostList) (data []*model.ApiPostDetail, err error) {
	// 2. 去redis查询id列表
	ids, err := redis.GetPostIDsInOrder(p)
	if err != nil {
		return
	}
	if len(ids) == 0 {
		zap.L().Warn("redis.GetPostIDsInOrder(p) return 0 data")
		return
	}
	zap.L().Debug("GetPostList2", zap.Any("ids", ids))
	// 3. 根据id去MySQL数据库查询帖子详细信息
	// 返回的数据还要按照我给定的id的顺序返回
	posts, err := dao.GetPostListByIDs(ids)
	if err != nil {
		return
	}
	zap.L().Debug("GetPostList2", zap.Any("posts", posts))
	// 提前查询好每篇帖子的投票数
	voteData, err := redis.GetPostVoteData(ids)
	if err != nil {
		return
	}

	// 将帖子的作者及分区信息查询出来填充到帖子中
	for idx, post := range posts {
		// 根据作者id查询作者信息
		user, err := dao.GetUserById(post.AuthorID)
		if err != nil {
			zap.L().Error("mysql.GetUserById(post.AuthorID) failed",
				zap.Int64("author_id", post.AuthorID),
				zap.Error(err))
			continue
		}
		// 根据社区id查询社区详细信息
		community, err := dao.GetCommunityDetailByID(post.CommunityID)
		if err != nil {
			zap.L().Error("mysql.GetUserById(post.AuthorID) failed",
				zap.Int64("community_id", post.CommunityID),
				zap.Error(err))
			continue
		}
		postDetail := &model.ApiPostDetail{
			AuthorName:      user.Username,
			VoteNum:         voteData[idx],
			Post:            post,
			CommunityDetail: community,
		}
		data = append(data, postDetail)
	}
	return

}

func GetCommunityPostList(p *model.PostList) (data []*model.ApiPostDetail, err error) {
	// 2. 去redis查询id列表
	ids, err := redis.GetCommunityPostIDsInOrder(p)
	if err != nil {
		return
	}
	if len(ids) == 0 {
		zap.L().Warn("redis.GetPostIDsInOrder(p) return 0 data")
		return
	}
	zap.L().Debug("GetCommunityPostIDsInOrder", zap.Any("ids", ids))
	// 3. 根据id去MySQL数据库查询帖子详细信息
	// 返回的数据还要按照我给定的id的顺序返回
	posts, err := dao.GetPostListByIDs(ids)
	if err != nil {
		return
	}
	zap.L().Debug("GetPostList2", zap.Any("posts", posts))
	// 提前查询好每篇帖子的投票数
	voteData, err := redis.GetPostVoteData(ids)
	if err != nil {
		return
	}

	// 将帖子的作者及分区信息查询出来填充到帖子中
	for idx, post := range posts {
		// 根据作者id查询作者信息
		user, err := dao.GetUserById(post.AuthorID)
		if err != nil {
			zap.L().Error("mysql.GetUserById(post.AuthorID) failed",
				zap.Int64("author_id", post.AuthorID),
				zap.Error(err))
			continue
		}
		// 根据社区id查询社区详细信息
		community, err := dao.GetCommunityDetailByID(post.CommunityID)
		if err != nil {
			zap.L().Error("mysql.GetUserById(post.AuthorID) failed",
				zap.Int64("community_id", post.CommunityID),
				zap.Error(err))
			continue
		}
		postDetail := &model.ApiPostDetail{
			AuthorName:      user.Username,
			VoteNum:         voteData[idx],
			Post:            post,
			CommunityDetail: community,
		}
		data = append(data, postDetail)
	}
	return
}

// GetPostListNew  将两个查询帖子列表逻辑合二为一的函数
func GetPostListNew(p *model.PostList) (data []*model.ApiPostDetail, err error) {
	// 根据请求参数的不同，执行不同的逻辑。
	if p.CommunityID == 0 {
		// 查所有
		data, err = GetPostList2(p)
	} else {
		// 根据社区id查询
		data, err = GetCommunityPostList(p)
	}
	if err != nil {
		zap.L().Error("GetPostListNew failed", zap.Error(err))
		return nil, err
	}
	return
}

// VoteForPost 为帖子投票的函数
func VoteForPost(userID int64, p *model.VoteData) error {
	return redis.VoteForPost(strconv.Itoa(int(userID)), p.PostID, float64(p.Direction))
}
